﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathCalculations;
using TargetingInfo;
using System.Threading;

namespace MissileControl
{
    public class MissileControl
    {
        List<Thread> listOfThreads;
        List<object> listofThreadParams;
        Thread mainLoop;
        Thread currentThread;
        object lock1;
        int h0;
        int v0;

        MissileLauncher ml;
        public MissileControl()
        {
            ml = new MissileLauncher();
            listOfThreads = new List<Thread>();
            listofThreadParams = new List<object>();
            mainLoop = new Thread(new ThreadStart(DoWork));
            lock1 = new object();
            h0 = 0;
            v0 = 0;
        }

        private void DoWork()
        {
            while (true)
            {
                if (listOfThreads.Count > 0)
                {
                    lock (lock1)
                    {
                        currentThread = listOfThreads[0];
                        object o = listofThreadParams[0];
                        listOfThreads.RemoveAt(0);
                        listofThreadParams.RemoveAt(0);
                        if (o == null)
                        {
                            currentThread.Start();
                        }
                        else
                        {
                            currentThread.Start(o);
                        }
                    }
                }
                Thread.Sleep(100);
            }
        }
        public void startThread()
        {
            mainLoop.Start();
        }

        public void stopThread()
        {
            mainLoop.Abort();
            if(currentThread !=null)
            {
                currentThread.Abort();
            }

            listofThreadParams = new List<object>();
            listOfThreads = new List<Thread>();
        }
        public void ResetCommand()
        {
            listOfThreads.Add(new Thread(new ThreadStart(reset)));
            listofThreadParams.Add(null);
        }
        public void AimAndFire(TargetInfo ti)
        {
            if (ti.IsFoe)
            {
                //ml.command_reset();
                //listOfThreads.Add(new Thread(new ThreadStart(reset)));
                //listofThreadParams.Add(null);
                AngleCalculation ac = new AngleCalculation();
                //eventually set the speed from the properties.
                double h1 = ac.getHorizontalAngle(ti.X, ti.Z);
                double v1 = ac.getVerticalAngle(ti.X, ti.Y, ti.Z);
                int h = convertToTime(h1);
                int v = convertToTimeVertical(v1);
                if (h0 > 0)
                {
                    listOfThreads.Add(new Thread(new ParameterizedThreadStart(left)));
                    listofThreadParams.Add(h0);

                    //ml.command_Left(-h);
                }
                else
                {
                    listOfThreads.Add(new Thread(new ParameterizedThreadStart(right)));
                    listofThreadParams.Add(-h0);
                    //ml.command_Right(h);
                }
                if (v0 < 0)
                {
                    listOfThreads.Add(new Thread(new ParameterizedThreadStart(down)));
                    listofThreadParams.Add(v0);
                    //ml.command_Down(-v);
                }
                else
                {
                    listOfThreads.Add(new Thread(new ParameterizedThreadStart(up)));
                    listofThreadParams.Add(-v0);
                    //ml.command_Up(v);
                }
                h0 = h;
                v0 = v;
                if (h < 0)
                {
                    listOfThreads.Add(new Thread(new ParameterizedThreadStart(left)));
                    listofThreadParams.Add(-h);

                    //ml.command_Left(-h);
                }
                else
                {
                    listOfThreads.Add(new Thread(new ParameterizedThreadStart(right)));
                    listofThreadParams.Add(h);
                    //ml.command_Right(h);
                }
                if (v < 0)
                {
                    listOfThreads.Add(new Thread(new ParameterizedThreadStart(down)));
                    listofThreadParams.Add(-v);
                    //ml.command_Down(-v);
                }
                else
                {
                    listOfThreads.Add(new Thread(new ParameterizedThreadStart(up)));
                    listofThreadParams.Add(v);
                    //ml.command_Up(v);
                }
                
                listOfThreads.Add(new Thread(new ThreadStart(fire)));
                listofThreadParams.Add(null);
                //ml.command_Fire();//*/
            }
        }
        public void FireRemaining()
        {
            listOfThreads.Add(new Thread(new ThreadStart(fire)));
            listofThreadParams.Add(null);
            listOfThreads.Add(new Thread(new ThreadStart(fire)));
            listofThreadParams.Add(null);

        }

        private void reset()
        {
            lock (lock1)
            {
                ml.command_reset();
            }
        }
        private void left(object d)
        {
            lock (lock1)
            { ml.command_Left((int)d); }
        }
        private void right(object d)
        {
            lock (lock1)
            { ml.command_Right((int)d); }
        }
        private void up(object d)
        {
            lock (lock1)
            { ml.command_Up((int)d); }
        }
        private void down(object d)
        {
            lock (lock1)
            { ml.command_Down((int)d); }
        }
        private void fire()
        {
            lock (lock1)
            { ml.command_Fire(); }
        }
        private int convertToTime(double degrees)
        {
            return Convert.ToInt32(Math.Floor(degrees * 180 / 9));
        }
        private int convertToTimeVertical(double degrees)
        {
            return Convert.ToInt32(Math.Floor(degrees * 7.2));
        }

    }
}
